import { Intersection, Object3D } from "three";
import { Raycaster } from "../../thirdparty/three/imports";
import { Camera3D } from "../cameras/Camera3D";
import { Node3D } from "./Node3D";

export class Raycaster3D
{
    _raycaster: Raycaster;

    constructor()
    {
        this._raycaster = new Raycaster();
    }

    setFromCamera(coords: { x: number; y: number; }, camera: Camera3D)
    {
        this._raycaster.setFromCamera(coords, camera._camera);
    }

    intersectObjects(objects: Node3D[], recursive?: boolean)
    {
        const groups = objects.map((v) => v._group.children[0]);

        const result = this._raycaster.intersectObjects(groups, recursive);

        return result;
    }

    intersectObject(object: Node3D, recursive?: boolean, optionalTarget?: Intersection3D[])
    {
        optionalTarget = optionalTarget || [];

        const intersects = optionalTarget.map((v) => v._intersection);

        const intersections = this._raycaster.intersectObject(object._group.children[0], recursive, intersects);

        intersections.forEach((v, i) =>
        {
            optionalTarget[i] = Intersection3D.get(v);
        });

        return optionalTarget;
    }
}

export class Intersection3D
{
    _intersection: Intersection<Object3D<Event>>;

    get point()
    {
        return this._intersection.point;
    }
    set point(v)
    {
        this._intersection.point = v;
    }

    get face()
    {
        return this._intersection.face;
    }
    set face(v)
    {
        this._intersection.face = v;
    }

    get instanceId()
    {
        return this._intersection.instanceId;
    }
    set instanceId(v)
    {
        this._intersection.instanceId = v;
    }

    static get(intersection: Intersection<Object3D<Event>>)
    {
        let intersection3D = this._map.get(intersection);
        if (!intersection3D)
        {
            intersection3D = new Intersection3D();
            intersection3D._intersection = intersection;
            this._map.set(intersection, intersection3D);
        }

        return intersection3D;
    }
    private static _map = new Map<Intersection<Object3D<Event>>, Intersection3D>();
}
